//
//  KATRouter.h
//  KATFramework
//
//  Created by Kantice on 2017/4/25.
//  Copyright © 2017年 KatApp. All rights reserved.
//  视图控制器切换路由器
//  AppDelegate需要实现生命周期代理方法
//
//  Action分为:
//  1.一般Action: 由id类型作为observer，添加后主动调用执行；
//  2.HostAction: 由host作为observer，执行action时会跳转到该host；
//  3.Mission: 由日志状态触发的action，分为日期、时长、事件次数三类触发模式；
//  三种action独立储存，由action的名称作为标识，添加相同的标识会覆盖当前的action。



#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h>

#import "KATHashMap.h"
#import "KATStack.h"
#import "KATTreeMap.h"
#import "KATDateUtil.h"
#import "KATURIParser.h"
#import "KATAppUtil.h"
#import "KATTabBar.h"
#import "KATNavBar.h"
#import "KATHttpRequest.h"
#import "KATImageUtil.h"

#import "KATAlertWindow.h"
#import "KATButtonWindow.h"
#import "KATChoiceWindow.h"
#import "KATInputWindow.h"
#import "KATTextFieldWindow.h"
#import "KATWaitWindow.h"
#import "KATToast.h"





@class KATTabBar;
@class KATNavBar;
@class KATNavTransition;


///根视图控制器的host
extern NSString * const kRouterRootHost;

///全局数据容器的host
extern NSString * const kRouterGlobalHost;

///执行者host
extern NSString * const kRouterExecutorHost;

///远程消息
extern NSString * const kRouterNotificationTypeRemote;

///本地消息
extern NSString * const kRouterNotificationTypeLocal;

///消息类型的key
extern NSString * const kRouterKeyMessageType;

///通知类型的key
extern NSString * const kRouterKeyNotificationType;

///scheme的key
extern NSString * const kRouterKeyScheme;

///user的key
extern NSString * const kRouterKeyUser;

///host的key
extern NSString * const kRouterKeyHost;

///fromHost的key
extern NSString * const kRouterKeyFromHost;

///toHost的key
extern NSString * const kRouterKeyToHost;

///是否回退的key
extern NSString * const kRouterKeyBackward;

///port的key
extern NSString * const kRouterKeyPort;

///path的key
extern NSString * const kRouterKeyPath;

///附加对象的key
extern NSString * const kRouterKeyAddition;

///fragment的key
extern NSString * const kRouterKeyFragment;

///默认的转场动画风格的key
extern NSString * const kRouterKeyTransitionStyle;

///默认的转场动画时长的key
extern NSString * const kRouterKeyTransitionDuration;

///默认的是否路由时新建实例的key
extern NSString * const kRouterKeyRoutingWithNewInstance;

///默认的是否路由时创建多例的key
extern NSString * const kRouterKeyRoutingWithMultipleInstance;

///fromHost的截图
extern NSString * const kRouterKeyFromHostSnapshot;




/*  日志
 
    app和host的进入离开记录会自动记录，event需要手动添加代码到需要记录的位置
    日志文件按日保存，文件名格式:yyyymmdd.log 如20140528.log

    内容结构:
    {
        "date":"20140528",
        
        "logs": //日志数组
        [
            //日志根节点
            {
                "id":"u12345678", //日志的id(用户ID)
 
                "date":"20140528", //记录的日期
 
                "num":"201405280000001", //记录编号(日期_自增序号)(唯一)
     
                "enter":"20140528220101", //app进入时间
         
                "hosts": //host跳转记录数组(根据数据顺序排列)
                [
                    //跳转的host单次记录(每次跳转都分别记录)
                    {
                        "host":"mine", //host名称
         
                        "uri":"app://mine/login?name=kat", //跳转时传入的URI
         
                        "enter":"20140528220101", //host进入时间
         
                        "events": //action触发记录数组
                        [
                            //触发的单次事件
                            {
                                "event":"mine.login", //事件名称(最好能以host为前缀保持唯一性)
                                
                                "time":"201405282201010000", //事件触发时间，精确到毫秒
         
                                "tag":"1", //事件的标签(整数，默认为0)
         
                                "msg":"test message", //事件携带的消息(整数，默认为空)
         
                                ... //其他属性(待定)
                            },
         
                            ... //其他事件
                        ],
         
                        "leave":"20140528220231", //host离开时间
         
                        "duration":"30", //host停留时间(单位为秒)
         
                        ... //其他属性(待定)
                    },
         
                    ... //其他host记录
                ],
         
                "leave":"20140528220201", //app离开时间
         
                "duration":"60", //app持续使用时间(单位为秒)
         
                "status":"0", //状态(0表示未知,1表示已上传,其他状态待定)
                
                ... //其他属性(待定)
            },
        
            ... //其他日志
        ]
    }

*/


///日志:默认的上传内容属性名
extern NSString * const kRouterLogsUploadContentDefaultKey;

///日志:id的key
extern NSString * const kRouterLogsKeyID;

///日志:日期的key
extern NSString * const kRouterLogsKeyDate;

///日志:该日的日志数组
extern NSString * const kRouterLogsKeyLogs;

///日志:编号的key
extern NSString * const kRouterLogsKeyLogNum;

///日志:日期的key
extern NSString * const kRouterLogsKeyLogDate;

///日志:日期的key
extern NSString * const kRouterLogsKeyLogStatus;

///日志:app进入时间key
extern NSString * const kRouterLogsKeyAppEnterTime;

///日志:app离开时间key
extern NSString * const kRouterLogsKeyAppLeaveTime;

///日志:app持续使用时间key
extern NSString * const kRouterLogsKeyAppDuration;

///日志:host跳转记录数组key
extern NSString * const kRouterLogsKeyHosts;

///日志:每次展现的host的根节点key
extern NSString * const kRouterLogsKeyHost;

///日志:host进入时间key
extern NSString * const kRouterLogsKeyHostEnterTime;

///日志:host离开时间key
extern NSString * const kRouterLogsKeyHostLeaveTime;

///日志:host停留时间key
extern NSString * const kRouterLogsKeyHostDuration;

///日志:每次跳转到该host的URI的key
extern NSString * const kRouterLogsKeyHostURI;

///日志:事件记录数组key
extern NSString * const kRouterLogsKeyEvents;

///日志:事件名称key
extern NSString * const kRouterLogsKeyEvent;

///日志:事件所带的消息key
extern NSString * const kRouterLogsKeyEventMessage;

///日志:事件触发时间key
extern NSString * const kRouterLogsKeyEventTime;

///日志:事件tag的key
extern NSString * const kRouterLogsKeyEventTag;




//转场动画风格枚举
typedef NS_ENUM(NSUInteger, KATRouterTransitionStyle)
{
    KATRouterTransitionStyleNone=0,
    KATRouterTransitionStyleFade,
    KATRouterTransitionStyleMoveHorizontal,
    KATRouterTransitionStyleMoveVertical,
    KATRouterTransitionStylePushHorizontal,
    KATRouterTransitionStylePushVertical,
    KATRouterTransitionStyleRevealHorizontal,
    KATRouterTransitionStyleRevealVertical,
    KATRouterTransitionStyleCubeHorizontal,
    KATRouterTransitionStyleCubeVertical,
    KATRouterTransitionStyleFlipHorizontal,
    KATRouterTransitionStyleFlipVertical,
    KATRouterTransitionStyleSuck,
    KATRouterTransitionStyleRipple,
    KATRouterTransitionStyleCurlLeft,
    KATRouterTransitionStyleCurlRight,
    KATRouterTransitionStyleCurlBottom,
    KATRouterTransitionStyleNavHorizontal,
    KATRouterTransitionStyleNavVertical
};



//app状态枚举
typedef NS_ENUM(NSUInteger, KATRouterAppStatus)
{
    KATRouterAppStatusUnknown=0,
    KATRouterAppStatusBecomeActive,
    KATRouterAppStatusResignActive,
    KATRouterAppStatusEnterForeground,
    KATRouterAppStatusEnterBackground,
    KATRouterAppStatusTerminate,
    KATRouterAppStatusOpenedWithURL
};



//路由器协议
@protocol KATRouterDelegate <NSObject>

@optional

#pragma -mark 消息

///路由跳转完成后
- (void)routingFinishWithValues:(KATHashMap *)values backward:(BOOL)backward;

///路由跳转将要开始
- (void)routingBeginWithValues:(KATHashMap *)values backward:(BOOL)backward;

///路由跳转到其他VC
- (void)routingDismissWithValues:(KATHashMap *)values backward:(BOOL)backward;

///是否允许路由跳转(VC上将要执行路由跳转行为时触发，返回YES表示允许，若没有实现该回调方法，则都允许路由)(对侧滑回退无效)
- (BOOL)allowRoutingWithValues:(KATHashMap *)values;

///接收到消息
- (void)receivedRouterMessage:(KATHashMap *)message;

///VC实例将要被释放
- (void)instanceWillBeReleased;


#pragma -mark 导航栏

///返回导航栏标题
- (NSString *)titleInNavBar:(KATNavBar *)navBar;

///返回导航栏图标
- (UIImage *)iconInNavBar:(KATNavBar *)navBar;

///返回导航栏按钮(不用配置Frame、颜色、缩放和粗细，只用配置类型和回调)
- (KATButton *)buttonInNavBar:(KATNavBar *)navBar;

///是否隐藏导航栏返回按钮
- (BOOL)hideBackButtonInNavBar:(KATNavBar *)navBar;

///是否显示导航栏(返回NO，或者未实现该方法，则会自动隐藏)
- (BOOL)isShownNavBar:(KATNavBar *)navBar;


#pragma -mark app状态

///App激活
- (void)appDidBecomeActive;

///App将要退出活跃
- (void)appWillResignActive;

///App将要进入前台
- (void)appWillEnterForeground;

///App进入后台
- (void)appDidEnterBackground;

///App将要终止
- (void)appWillTerminate;

///App通过URL中打开(此回调方法只在页面没有发生跳转的情况下正确执行，若有跳转，则会执行跳转前的VC的该回调方法，默认会发生跳转，推荐在routingFinishWithValues:回调方法中处理事件)
- (BOOL)appOpenedWithURL:(NSURL *)url andInfo:(KATHashMap *)info;

///App接收到通知(本地或远程)
- (void)appReceivedNotification:(KATHashMap *)info;

///App注册远程通知
- (void)appRegisteredRemoteNotificationWithDeviceToken:(NSData *)deviceToken;



@end




@interface KATRouter : NSObject


#pragma -mark App代理回调及动作(先执行该动作，再执行VC代理的回调方法)

///设置App激活动作
+ (void)setAppDidBecomeActiveAction:(BOOL (^)(void))action;

///设置App将要退出活跃动作
+ (void)setAppWillResignActiveAction:(BOOL (^)(void))action;

///设置App将要进入前台动作(此动作有默认值，即徽标清零)
+ (void)setAppWillEnterForegroundAction:(BOOL (^)(void))action;

///设置App进入后台动作
+ (void)setAppDidEnterBackgroundAction:(BOOL (^)(void))action;

///设置App将要终止动作
+ (void)setAppWillTerminateAction:(BOOL (^)(void))action;

///设置App通过URL中打开动作(此动作有默认值，即跳转到URL)(因为没有对应的系统通知，需要在AppDlelgate中实现application:openURL:options:方法，空实现亦可)
+ (void)setAppOpenedWithURLAction:(BOOL (^)(NSURL *url,KATHashMap *info))action;

///设置App收到通知(本地或远程)动作
+ (void)setAppReceivedNotificationAction:(BOOL (^)(KATHashMap *info))action;

///设置App注册远程通知动作
+ (void)setAppRegisterNotificationAction:(BOOL (^)(NSData *deviceToken))action;

///设置路由跳转时的动作(只针对routeWithURI:和routeWithURI:addition:方法)
+ (void)setRouteWithURIAction:(KATHashMap *(^)(KATHashMap *uri,id addition))action;

///设置路由跳转时的动作(所有跳转方法)
+ (void)setRouteAction:(void (^)(KATHashMap *values))action;

///设置定时器动作(与时长任务共用一个定时器，优先执行改动作，再执行任务)
+ (void)setTimerAction:(void (^)(void))action;


#pragma -mark 注册

///通过类注册视图控制器,host为标识
+ (BOOL)registerClass:(Class)cls withHost:(NSString *)host;

///通过类名注册视图控制器,host为标识
+ (BOOL)registerWithClassName:(NSString *)className andHost:(NSString *)host;

///通过实例注册视图控制器,host为标识
+ (BOOL)registerInstance:(UIViewController *)vc withHost:(NSString *)host;

///删除注册的视图控制器
+ (BOOL)removeRegisteredHost:(NSString *)host;


#pragma -mark 标签栏

///设置标签栏(默认为空)
+ (void)setTabBar:(KATTabBar *)tabBar;

///设置是否自动隐藏标签栏(非关联标签栏的host)(默认为否)
+ (void)setIsAutoHidingTabBar:(BOOL)hidding;

///隐藏标签栏
+ (void)hideTabBar;

///显示标签栏
+ (void)showTabBar;

///刷新标签栏
+ (void)updateTabBar;

///选中标签
+ (void)selectTabWithIndex:(unsigned)index;

///选中标签
+ (void)selectTabWithHost:(NSString *)host;

///添加徽标
+ (void)addBadgeToTabWithIndex:(unsigned)index;

///添加徽标
+ (void)addBadgeToTabWithHost:(NSString *)host;

///删除徽标
+ (void)removeBadgeFromTabWithIndex:(unsigned)index;

///删除徽标
+ (void)removeBadgeFromTabWithHost:(NSString *)host;

///清除所有的徽标
+ (void)clearBadgesFromTabBar;

///获取标签栏
+ (KATTabBar *)getTabBar;

///获取tab栏选中的host
+ (NSString *)hostInSelectedTab;

///获取tab栏选中的URI
+ (NSString *)URIInSelectedTab;


#pragma -mark 导航栏

///设置导航栏(默认有)
+ (void)setNavBar:(KATNavBar *)navBar;

///隐藏导航栏
+ (void)hideNavBar;

///显示导航栏
+ (void)showNavBar;

///刷新导航栏
+ (void)updateNavBar;

///获取导航栏
+ (KATNavBar *)getNavBar;


#pragma -mark 横竖屏

///设置默认屏幕方向是否为横屏
+ (void)setDefaultOrientationLandscape:(BOOL)isLandscapeDefault;

///添加竖屏方向的host数组
+ (void)addPortraitOrientationHosts:(KATArray<NSString *> *)hosts;

///添加竖屏方向的host
+ (void)addPortraitOrientationHost:(NSString *)host;

///删除竖屏方向的host
+ (void)removePortraitOrientationHost:(NSString *)host;

///清除竖屏方向的host
+ (void)clearPortraitOrientationHosts;

///添加横屏方向的host数组
+ (void)addLandscapeOrientationHosts:(KATArray<NSString *> *)hosts;

///添加横屏方向的host
+ (void)addLandscapeOrientationHost:(NSString *)host;

///删除横屏方向的host
+ (void)removeLandscapeOrientationHost:(NSString *)host;

///清除横屏方向的host
+ (void)clearLandscapeOrientationHosts;

///添加自由方向的host数组
+ (void)addFreeOrientationHosts:(KATArray<NSString *> *)hosts;

///添加自由方向的host
+ (void)addFreeOrientationHost:(NSString *)host;

///删除自由方向的host
+ (void)removeFreeOrientationHost:(NSString *)host;

///清除自由方向的host
+ (void)clearFreeOrientationHosts;


#pragma -mark 日志记录 (当日日志根据当日app首次进入时间算)

///设置日志保存目录(只设置一次)(Documents下)
+ (void)setLogsDirectory:(NSString *)dir;

///更改日志保存目录(Documents下)
+ (void)changeLogsDirectory:(NSString *)dir;

///获取历史日志
+ (KATTreeMap<KATHashMap *> *)getHistoryLogs;

///获取当日日志
+ (KATHashMap *)getDayLogs;

///获取本次app使用的日志
+ (KATHashMap *)getAppLog;

///获取当前host的日志
+ (KATHashMap *)getHostLog;

///清空日志
+ (void)clearLogs;

///设置是否保存日志(默认保存日志)(只设置一次)
+ (void)setShouldKeepLogs:(BOOL)keep;

///更改是否保存日志(默认保存日志)
+ (void)changeShouldKeepLogs:(BOOL)keep;

///设置日志保留时间(单位日,默认60日，最多保存1000日)(只设置一次)
+ (void)setLogsKeepingDays:(int)days;

///更改日志保留时间(单位日,默认60日，最多保存1000日)
+ (void)changeLogsKeepingDays:(int)days;

///获取日志上传地址
+ (NSString *)getLogsUploadURL;

///设置日志上传地址(只设置一次)
+ (void)setLogsUploadURL:(NSString *)URL;

///更改日志上传地址
+ (void)changeLogsUploadURL:(NSString *)URL;

///获取日志用户ID
+ (NSString *)getLogsID;

///设置日志的用户ID(只设置一次)
+ (void)setLogsID:(NSString *)ID;

///更改日志的用户ID
+ (void)changeLogsID:(NSString *)ID;

///获取日志上传的内容属性名(只设置一次)
+ (NSString *)getLogsUploadContentKey;

///设置日志上传的内容属性名(只设置一次)
+ (void)setLogsUploadContentKey:(NSString *)key;

///更改日志上传的内容属性名
+ (void)changeLogsUploadContentKey:(NSString *)key;

///获取日志上传的附加信息(只设置一次)
+ (KATHashMap *)getLogsUploadExtra;

///设置日志上传的附加信息(只设置一次)
+ (void)setLogsUploadExtra:(KATHashMap *)extra;

///更改日志上传的附加信息
+ (void)changeLogsUploadExtra:(KATHashMap *)extra;

///设置是否上传日志(只设置一次)
+ (void)setShouldUploadLogs:(BOOL)upload;

///更改是否上传日志
+ (void)changeShouldUploadLogs:(BOOL)upload;

///设置日志上传后回调动作，返回是否成功(默认为空，为空时，若有数据返回，则认为上传成功)
+ (void)setLogsDidUploadAction:(BOOL (^)(NSString *feeback))action;

///标记事件(全参数)
+ (void)markEvent:(NSString *)event withTag:(long long)tag andMessage:(NSString *)msg;

///标记事件
+ (void)markEvent:(NSString *)event withTag:(long long)tag;

///标记事件
+ (void)markEvent:(NSString *)event withMessage:(NSString *)msg;

///标记事件
+ (void)markEvent:(NSString *)event;


#pragma -mark 日志分析

///当日的app的使用时长(单位:秒)
+ (long long)durationByDayUsing;

///当日指定用户的app的使用时长(单位:秒)(IDs为空时返回所有的)
+ (long long)durationByDayUsingWithIDs:(KATArray<NSString *> *)IDs;

///本次app的使用时长(单位:秒)
+ (long long)durationByAppUsing;

///在当前host停留的时长(单位:秒)
+ (long long)durationByHostUsing;

///获取最早一次日志到现在的天数(没有则返回负数)
+ (int)daysFromFirstLog;

///获取最近一次日志到现在的天数(没有则返回负数)
+ (int)daysFromLastLog;

///获取最早一次日志到现在的秒数(从日志的开始时间计算，没有则返回负数)
+ (long long)secondsFromFirstLog;

///获取最近一次日志到现在的秒数(从日志的结束时间计算，没有则返回负数)
+ (long long)secondsFromLastLog;

///获取最近一次host日志到现在的天数(没有则返回负数)
+ (int)daysFromLastUsingWithHost:(NSString *)host;

///获取最近一次事件到现在的天数(没有则返回负数)
+ (int)daysFromLastEvent:(NSString *)event;

///获取该host当日的使用秒数
+ (long long)secondsByDayUsingWithHost:(NSString *)host;

///获取该host数组当日的使用秒数
+ (long long)secondsByDayUsingWithHosts:(KATArray<NSString *> *)hosts;

///获取该host在本次app使用中的使用秒数
+ (long long)secondsByAppUsingWithHost:(NSString *)host;

///获取该host数组在本次app使用中的使用秒数
+ (long long)secondsByAppUsingWithHosts:(KATArray<NSString *> *)hosts;

///获取最近一次事件到现在的秒数(没有则返回负数)
+ (long long)secondsFromLastEvent:(NSString *)event;

///获取当日最近一次事件到现在的秒数(没有则返回负数)
+ (long long)secondsByDayUsingFromLastEvent:(NSString *)event;

///获取本次app使用中最近一次事件到现在的秒数(没有则返回负数)
+ (long long)secondsByAppUsingFromLastEvent:(NSString *)event;

///获取当前host中最近一次事件到现在的秒数(没有则返回负数)
+ (long long)secondsByHostUsingFromLastEvent:(NSString *)event;

///历史上触发该事件的总次数
+ (int)countInHistoryWithEvent:(NSString *)event;

///历史上触发该事件数组的总次数
+ (int)countInHistoryWithEvents:(KATArray<NSString *> *)events;

///当日触发该事件的次数
+ (int)countInDayUsingWithEvent:(NSString *)event;

///当日触发该事件数组的总次数
+ (int)countInDayUsingWithEvents:(KATArray<NSString *> *)events;

///多少日内触发该事件的次数(0代表当天，1代表当天和昨天)
+ (int)countInDays:(int)days withEvent:(NSString *)event;

///多少日内触发该事件数组的总次数(0代表当天，1代表当天和昨天)
+ (int)countInDays:(int)days withEvents:(KATArray<NSString *> *)events;

///本次app使用中触发该事件的次数
+ (int)countInAppUsingWithEvent:(NSString *)event;

///获取最近一次事件
+ (KATHashMap *)getLastEvent:(NSString *)event;

///获取指定ID的事件(从最近到最初的时间排序)(IDs为空时返回所有的)
+ (KATArray<KATHashMap *> *)eventsWithIDs:(KATArray<NSString *> *)IDs;

///本次app使用中触发该事件数组的总次数
+ (int)countInAppUsingWithEvents:(KATArray<NSString *> *)events;

///在当前host中触发该事件的次数
+ (int)countInHostUsingWithEvent:(NSString *)event;

///在当前host中触发该事件数组的总次数
+ (int)countInHostUsingWithEvents:(KATArray<NSString *> *)events;


#pragma -mark 任务(在主线程中执行,方法中不能带参数)(可以删除后再添加，但不能覆盖)

///添加未使用app的天数触发的任务(超过天数则触发)(app打开时判断执行)
+ (void)addMission:(NSString *)mission forUnusedDays:(unsigned int)days withObserver:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加未使用host的天数触发的任务(超过天数则触发)(app打开时判断执行)
+ (void)addMission:(NSString *)mission withHost:(NSString *)host forUnusedDays:(unsigned int)days observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加未触发事件的天数触发的任务(超过天数则触发)(app打开时判断执行)
+ (void)addMission:(NSString *)mission withEvent:(NSString *)event forUntriggeredDays:(unsigned int)days observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加当日使用时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byDayUsingForDuration:(unsigned int)seconds withObserver:(NSString *)observerHost andSelector:(NSString *)selector;

///添加app使用时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byAppUsingForDuration:(unsigned int)seconds withObserver:(NSString *)observerHost andSelector:(NSString *)selector;

///添加host停留时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byUsingHost:(NSString *)host forDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加app使用中host停留时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byAppUsingWithHost:(NSString *)host forDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加app使用中host数组总停留时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byAppUsingWithHosts:(KATArray<NSString *> *)hosts forDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加当日host停留时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byDayUsingWithHost:(NSString *)host forDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加当日host数组总停留时长任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission byDayUsingWithHosts:(KATArray<NSString *> *)hosts forDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加当日未触发事件时长的任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission withEvent:(NSString *)event forUntriggeredDuration:(unsigned int)seconds observer:(NSString *)observerHost andSelector:(NSString *)selector;

///添加定时任务(超过时长则触发，只触发一次)
+ (void)addMission:(NSString *)mission forDuration:(unsigned int)seconds withObserver:(NSString *)observerHost andSelector:(NSString *)selector;

///添加历史事件发生次数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission withEvent:(NSString *)event forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加历史事件数组发生总数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission withEvents:(KATArray<NSString *> *)events forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加当日事件发生次数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission byDayUsingWithEvent:(NSString *)event forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加当日事件数组发生总数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission byDayUsingWithEvents:(KATArray<NSString *> *)events forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加app使用时事件发生次数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission byAppUsingWithEvent:(NSString *)event forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///添加app使用时事件数组发生总数任务(到达该次数则触发，可设置触发次数)
+ (void)addMission:(NSString *)mission byAppUsingWithEvents:(KATArray<NSString *> *)events forCount:(unsigned int)count observer:(NSString *)observerHost selector:(NSString *)selector andTimes:(unsigned int)times;

///判断是否已经添加了该任务
+ (BOOL)hasMission:(NSString *)mission;

///删除任务
+ (void)removeMission:(NSString *)mission;

///清除所有任务
+ (void)clearMissions;


#pragma -mark 路由(跳转)(在主线程中进行)

///禁用路由(调用该方法后，路由将无法进行，直到启用路由)(在禁用期间的所有路由行为都将被取消)
+ (void)disableRouting;

///启用路由(默认为启用)
+ (void)enableRouting;

///暂停路由(调用该方法后，路由将无法进行，直到恢复路由，恢复后，原先的路由行为将继续执行)
+ (void)pauseRouting;

///恢复路由
+ (void)resumeRouting;

///路由
+ (void)routeWithURI:(NSString *)URI;

///路由
+ (void)routeWithURI:(NSString *)URI addition:(id)addition;

///路由
+ (void)routeWithURI:(NSString *)URI andHandle:(void (^)(void))handle;

///路由
+ (void)routeWithURI:(NSString *)URI addition:(id)addition andHandle:(void (^)(void))handle;

///路由(全参数)
+ (void)routeWithURI:(NSString *)URI selector:(SEL)sel object:(id)obj addition:(id)addition andHandle:(void (^)(void))handle;

///回退
+ (void)backward;

///回退(query不带问号)
+ (void)backwardWithQuery:(NSString *)query;

///回退
+ (void)backwardWithAddition:(id)addition;

///回退
+ (void)backwardWithHandle:(void (^)(void))handle;

///回退(全参数)(query不带问号)
+ (void)backwardWithQuery:(NSString *)query addition:(id)addition andHandle:(void (^)(void))handle;

///回退到指定的URI(该host必须在回退栈上才会执行，若栈上有多个该host，则回退到最顶端的host，执行时会清除栈顶到host之间的所有回退节点)
+ (void)backwardWithURI:(NSString *)URI addition:(id)addition andHandle:(void (^)(void))handle;

///路由到当前host(不带参数刷新当前host的方法，会触发回调，用于恢复导航栏、标签栏等操作)
+ (void)routeCurrent;

///路由到当前tab栏选中的host
+ (void)routeToTabBarSelectdHost;

///路由到当前tab栏选中的URI
+ (void)routeToTabBarSelectdURI;

///退回到当前tab栏选中的host
+ (void)backToTabBarSelectdHost;

///退回到当前tab栏选中的URI
+ (void)backToTabBarSelectdURI;


#pragma -mark 侧滑回退

///添加侧滑回退的host数组
+ (void)addSlideHosts:(KATArray<NSString *> *)hosts;

///添加侧滑回退的host
+ (void)addSlideHost:(NSString *)host;

///删除侧滑回退的host
+ (void)removeSlideHost:(NSString *)host;

///清除侧滑回退的host
+ (void)clearSlideHosts;

///添加禁止侧滑回退的host数组
+ (void)addSlideDisabledHosts:(KATArray<NSString *> *)hosts;

///添加禁止侧滑回退的host
+ (void)addSlideDisabledHost:(NSString *)host;

///删除禁止侧滑回退的host
+ (void)removeSlideDisabledHost:(NSString *)host;

///清除禁止侧滑回退的host
+ (void)clearSlideDisabledHosts;

///设置侧滑完成进度点(0~1之间 默认0.4,即超过宽度的40%)
+ (void)setSlideFinishProgress:(float)progress;

///设置侧滑手势完成条件的滑动尾速(默认为每帧16点)
+ (void)setSlideFinishSpeed:(float)speed;

///设置侧滑手势起始点X坐标位置(0~1之间,默认0.5,即左半屏)
+ (void)setSlideStartXPoint:(float)xPoint;

///设置水平滑动动画效果的host是否自动带侧滑交互(默认是)
+ (void)setSlideAutoSetting:(BOOL)autoSetting;


#pragma -mark 发送消息(不跳转，在receivedRouterMessage:回调方法中处理)

///发送消息到指定的host
+ (void)sendMessage:(KATHashMap *)message toHost:(NSString *)host;

///发送消息到当前的host
+ (void)sendMessage:(KATHashMap *)message;

///广播消息(发送消息给所有的已经实例化的Host)
+ (void)broadcastMessage:(KATHashMap *)message;

///广播指定类型的消息(发送消息给监听该类型消息的Host)
+ (void)broadcastMessage:(KATHashMap *)message withType:(NSString *)type;

///监听指定类型的消息(通过host指定)
+ (void)addObserverWithHost:(NSString *)host forMessageType:(NSString *)type;

///监听指定类型的消息(通过类指定)
+ (void)addObserverWithClass:(Class)cls forMessageType:(NSString *)type;

///监听指定类型的消息(通过类名指定)
+ (void)addObserverWithClassName:(NSString *)name forMessageType:(NSString *)type;

///监听指定类型的消息(通过实例指定)
+ (void)addObserverWithInstance:(UIViewController *)instance forMessageType:(NSString *)type;

///移除监听指定类型的消息(通过host移除)
+ (void)removeObserverWithHost:(NSString *)host forMessageType:(NSString *)type;

///移除监听指定类型的消息(通过类移除)
+ (void)removeObserverWithClass:(Class)cls forMessageType:(NSString *)type;

///移除监听指定类型的消息(通过类名移除)
+ (void)removeObserverWithClassName:(NSString *)name forMessageType:(NSString *)type;

///移除监听指定类型的消息(通过实例移除)
+ (void)removeObserverWithInstance:(UIViewController *)instance forMessageType:(NSString *)type;

///移除所有的监听消息
+ (void)removeObserverForAllMessageTypesWithHost:(NSString *)host;

///清除所有的消息及监听器
+ (void)clearMessageObservers;

///通过URI的方式发送消息
+ (void)noticeWithURI:(NSString *)URI;


#pragma -mark 执行动作

///添加执行动作(重复添加会覆盖)(方法最多带一个参数)
+ (void)addAction:(NSString *)action withObserver:(id)observer andSelector:(SEL)selector;

///移除执行动作
+ (void)removeAction:(NSString *)action;

///执行动作
+ (void)doAction:(NSString *)action;

///执行带参数的动作
+ (void)doAction:(NSString *)action withObject:(id)obj;

///清除所有动作
+ (void)clearActions;

///添加host执行动作(重复添加会覆盖)(方法最多带一个参数)
+ (void)addHostAction:(NSString *)action withHost:(NSString *)host andSelector:(NSString *)selector;

///移除host执行动作
+ (void)removeHostAction:(NSString *)action;

///执行host动作(执行时会跳转到该host)(主线程中执行)
+ (void)doHostAction:(NSString *)action;

///执行带参数的host动作(执行时会跳转到该host)(主线程中执行)
+ (void)doHostAction:(NSString *)action withObject:(id)obj;

///执行host动作(若forward为NO，且该host没有实例，则不执行)(主线程中执行)
+ (void)doHostAction:(NSString *)action withObject:(id)obj andForward:(BOOL)forward;

///清除所有的host动作
+ (void)clearHostActions;


#pragma -mark 变量存取

///获取变量(全局)
+ (id)getValueWithKey:(NSString *)key;

///通过host获取变量(未注册的host用全局容器)
+ (id)getValueWithKey:(NSString *)key andHost:(NSString *)host;

///通过VC实例获取变量(未注册的VC用全局容器)
+ (id)getValueWithKey:(NSString *)key andInstance:(UIViewController *)vc;

///设置变量(全局)
+ (void)setValue:(id)value WithKey:(NSString *)key;

///通过host设置变量(未注册的host用全局容器)
+ (void)setValue:(id)value WithKey:(NSString *)key andHost:(NSString *)host;

///通过VC实例设置变量(未注册的VC用全局容器)
+ (void)setValue:(id)value WithKey:(NSString *)key andInstance:(UIViewController *)vc;


#pragma -mark 参数配置

///设置首次路由URI(只设置一次)
+ (void)setFirstRouteURI:(NSString *)URI;

///更改首次路由URI
+ (void)changeFirstRouteURI:(NSString *)URI;

///获取首次路由URI
+ (NSString *)firstRouteURI;

///设置转场动画风格的key(方便传参数)(只设置一次)
+ (void)setTransitionStyleKey:(NSString *)key;

///更改转场动画风格的key(方便传参数)
+ (void)changeTransitionStyleKey:(NSString *)key;

///获取转场动画风格的key
+ (NSString *)transitionStyleKey;

///设置转场动画风格(只设置一次)
+ (void)setTransitionStyle:(KATRouterTransitionStyle)style;

///更改转场动画风格
+ (void)changeTransitionStyle:(KATRouterTransitionStyle)style;

///设置host的默认转场动画
+ (void)setTransitionStyle:(KATRouterTransitionStyle)style forHost:(NSString *)host;

///设置host数组的默认转场动画
+ (void)setTransitionStyle:(KATRouterTransitionStyle)style forHosts:(KATArray<NSString *> *)hosts;

///删除host的默认转场动画
+ (void)removeTransitionStyleFromHost:(NSString *)host;

///清除所有的host默认转场动画
+ (void)clearTransitionStyleFromAllHosts;

///设置转场动画时长的key(方便传参数)(只设置一次)
+ (void)setTransitionDurationKey:(NSString *)key;

///更改转场动画时长的key(方便传参数)
+ (void)changeTransitionDurationKey:(NSString *)key;

///获取转场动画时长的key
+ (NSString *)transitionDurationKey;

///设置转场动画时长(只设置一次)
+ (void)setTransitionDuration:(double)duration;

///更改转场动画时长
+ (void)changeTransitionDuration:(double)duration;

///设置路由时是否新建实例的key(方便传参数)(只设置一次)
+ (void)setRoutingWithNewInstanceKey:(NSString *)key;

///更改路由时是否新建实例的key(方便传参数)
+ (void)changeRoutingWithNewInstanceKey:(NSString *)key;

///获取路由时是否新建实例的key
+ (NSString *)routingWithNewInstanceKey;

///设置路由时是否创建多例的key(方便传参数)(只设置一次)
+ (void)setRoutingWithMultipleInstanceKey:(NSString *)key;

///更改路由时是否创建多例的key(方便传参数)
+ (void)changeRoutingWithMultipleInstanceKey:(NSString *)key;

///获取路由时是否创建多例的key
+ (NSString *)routingWithMultipleInstanceKey;

///设置根视图内容图片(默认为启动图片)
+ (void)setRootContents:(UIImage *)contents;

///设置定时器间隔
+ (void)setTimerInterval:(double)interval;

///设置路由最大等待时间(默认为转场动画最大时长)
+ (void)setRoutingWaitDuration:(double)duration;

///获取根视图控制器
+ (UIViewController *)rootViewController;

///获取栈顶host
+ (NSString *)topHost;

///获取栈顶VC(路由器中的栈顶，不一定是app中的栈顶)
+ (UIViewController *)topViewController;

///获取主窗口
+ (UIWindow *)keyWindow;



#pragma -mark 弹窗

///获取提示窗口(用于设置样式等)
+ (KATAlertWindow *)getAlertWindow;

///显示提示窗口(直接显示之前设置过的窗口)
+ (void)showAlertWindow;

///隐藏提示窗口
+ (void)hideAlertWindow;

///显示提示窗口(设置标题和信息)
+ (void)showAlertWindowWithTitle:(NSString *)title andInfo:(NSString *)info;

///获取按钮窗口(用于设置样式等)
+ (KATButtonWindow *)getButtonWindow;

///显示按钮窗口(直接显示之前设置过的窗口)
+ (void)showButtonWindow;

///隐藏按钮窗口
+ (void)hideButtonWindow;

///显示按钮窗口(设置标题、信息和确认按钮动作，默认带一个取消按钮和一个确认按钮)
+ (void)showButtonWindowWithTitle:(NSString *)title info:(NSString *)info andOnConfirmAction:(void (^)(void))action;

///显示按钮窗口(设置标题、信息和按钮)
+ (void)showButtonWindowWithTitle:(NSString *)title info:(NSString *)info andButtons:(KATArray<KATButton *> *)buttons;

///获取选择窗口(用于设置样式等)
+ (KATChoiceWindow *)getChoiceWindow;

///显示选择窗口(直接显示之前设置过的窗口)
+ (void)showChoiceWindow;

///隐藏选择窗口
+ (void)hideChoiceWindow;

///显示选择窗口(设置标题、信息和左右按钮标签及动作)
+ (void)showChoiceWindowWithTitle:(NSString *)title info:(NSString *)info leftButtonLabel:(NSString *)leftLabel leftButtonAction:(void (^)(void))leftAction rightButtonLabel:(NSString *)rightLabel rightButtonAction:(void (^)(void))rightAction;

///显示选择窗口(设置标题、信息和按钮)
+ (void)showChoiceWindowWithTitle:(NSString *)title info:(NSString *)info andButtons:(KATArray<KATLabelButton *> *)buttons;

///获取输入窗口(用于设置样式等)
+ (KATInputWindow *)getInputWindow;

///显示输入窗口(直接显示之前设置过的窗口)
+ (void)showInputWindow;

///隐藏输入窗口
+ (void)hideInputWindow;

///显示输入窗口(设置标题和确认动作)
+ (void)showInputWindowWithTitle:(NSString *)title andOnConfirmAction:(void (^)(NSString *text))action;

///获取输入框窗口(用于设置样式等)
+ (KATTextFieldWindow *)getTextFieldWindow;

///显示输入框窗口(直接显示之前设置过的窗口)
+ (void)showTextFieldWindow;

///隐藏输入框窗口
+ (void)hideTextFieldWindow;

///显示输入框窗口(设置标题、信息和左右按钮标签及动作)
+ (void)showTextFieldWindowWithTitle:(NSString *)title leftButtonLabel:(NSString *)leftLabel leftButtonAction:(void (^)(NSString *text))leftAction rightButtonLabel:(NSString *)rightLabel rightButtonAction:(void (^)(NSString *text))rightAction;

///获取等待窗口(用于设置样式等)
+ (KATWaitWindow *)getWaitWindow;

///显示等待窗口(直接显示之前设置过的窗口)
+ (void)showWaitWindow;

///隐藏等待窗口
+ (void)hideWaitWindow;

///获取加载窗口(用于设置样式等)
+ (KATWaitWindow *)getLoadingWindow;

///显示加载窗口(直接显示之前设置过的窗口)
+ (void)showLoadingWindow;

///隐藏加载窗口
+ (void)hideLoadingWindow;

///加载完成
+ (void)loadingWindowSuccessWithMessage:(NSString *)message;

///加载失败
+ (void)loadingWindowFailWithMessage:(NSString *)message;

///获取吐司(用于设置样式等)
+ (KATToast *)getToast;

///显示吐司(直接显示之前设置过的窗口)
+ (void)showToast;

///显示吐司(设置文本)
+ (void)showToastWithText:(NSString *)text;

///显示吐司(设置按钮)
+ (void)showToastWithButton:(KATButtonType)button;

///显示吐司(设置文本、按钮、时长和位置)
+ (void)showToastWithText:(NSString *)text button:(KATButtonType)button duration:(float)duration andPosition:(int)position;



#pragma -mark 内容管理

///是否正在跳转
+ (BOOL)isRouting;

///通过类获取host
+ (NSString *)hostWithClass:(Class)cls;

///通过类名获取host
+ (NSString *)hostWithClassName:(NSString *)name;

///通过实例获取host
+ (NSString *)hostWithInstance:(UIViewController *)instance;

///获取当前的host
+ (NSString *)currentHost;

///正在路由的host
+ (NSString *)routingHost;

///获取当前的host的实例
+ (UIViewController *)currentHostInstance;

///判断是否为当前的host
+ (BOOL)isCurrentHost:(NSString *)host;

///判断是否为当前的host实例
+ (BOOL)isCurrentHostInstance:(UIViewController *)instance;

///获取类
+ (Class)classWithHost:(NSString *)host;

///获取实例
+ (UIViewController *)instanceWithHost:(NSString *)host;

///释放实例
+ (void)releaseInstance:(UIViewController *)instance;

///释放实例
+ (void)releaseInstanceWithHost:(NSString *)host;

///释放所有实例
+ (void)releaseAllInstances;

///添加一直持有的host
+ (void)addAlwaysRetainedHost:(NSString *)host;

///添加一直持有的host数组
+ (void)addAlwaysRetainedHosts:(KATArray<NSString *> *)hosts;

///删除一直持有的host
+ (void)removeAlwaysRetainedHost:(NSString *)host;

///添加路由时新建实例的host
+ (void)addRoutingWithNewInstanceHost:(NSString *)host;

///添加路由时新建实例的host数组
+ (void)addRoutingWithNewInstanceHosts:(KATArray<NSString *> *)hosts;

///删除路由时新建实例的host
+ (void)removeRoutingWithNewInstanceHost:(NSString *)host;

///添加路由时创建多例的host
+ (void)addRoutingWithMultipleInstanceHost:(NSString *)host;

///添加路由时创建多例的host数组
+ (void)addRoutingWithMultipleInstanceHosts:(KATArray<NSString *> *)hosts;

///删除路由时创建多例的host
+ (void)removeRoutingWithMultipleInstanceHost:(NSString *)host;

///添加需要接收截图的host
+ (void)addRequeredSnapshotHost:(NSString *)host;

///添加需要接收截图的host数组
+ (void)addRequeredSnapshotHosts:(KATArray<NSString *> *)hosts;

///删除需要接收截图的host
+ (void)removeRequeredSnapshotHost:(NSString *)host;

///获取返回栈
+ (KATStack<NSString *> *)backwardStack;

///将host插入到返回栈上的目标host之下
+ (BOOL)insertHost:(NSString *)host toBackwardStack:(NSString *)targetHost;

///将host插入到返回栈上的目标host之上
+ (BOOL)appendHost:(NSString *)host toBackwardStack:(NSString *)targetHost;

///将host插入到返回栈上的栈顶
+ (BOOL)appendToBackwardStackWithHost:(NSString *)host;

///将返回栈上的host删除
+ (void)removeHostFromBackwardStack:(NSString *)host;

///释放路由器
+ (void)releaseRouter;


@end

